<template>
    <div class="search-controller-box q-col">
        <el-form-item :class="{ 'search-form-item': lastml }">
            <slot></slot>
            <el-button
                v-if="!isCloseOpen && isOpen"
                type="primary"
                text
                :bg="false"
                class="search-controller-tool"
                @click="handleOpen"
            >
                {{ toolText }}
                <el-icon v-if="!needOpenStatus" style="margin-left: 4px">
                    <ArrowDown />
                </el-icon>
                <el-icon v-else style="margin-left: 4px">
                    <ArrowUp />
                </el-icon>
            </el-button>
        </el-form-item>
    </div>
</template>

<script setup lang="ts">
import { ArrowDown, ArrowUp } from '@element-plus/icons-vue';
import { getDom, getDomList } from '@/utils';

const props = withDefaults(
    defineProps<{
        index?: number;
        refresh?: number | boolean;
        isCloseOpen?: boolean;
        searchRef?: HTMLDivElement;
    }>(),
    {
        index: 0,
        refresh: false
    }
);

const toolText = ref('展开');
const isOpen = ref(false);
const needOpenStatus = ref(false);
const lastml = ref(true);
const expand = ref(false);
const parentDOM = ref<HTMLElement | null>(null);
const inputList = ref<NodeListOf<HTMLElement>>();
const box = ref<HTMLElement>();
watch(
    () => props.refresh,
    val => {
        if (val) {
            needOpenStatus.value = !expand.value;
            setDisplay(inputList.value, 'block');
            computeCol();
            handleOpen();
        }
    }
);

onBeforeMount(() => {
    initData();
});
onMounted(() => {
    computeCol();
});

const initData = () => {
    if (expand.value) {
        // 默认展开 expand 由 全局 app.config.globalProperties 挂载属性
        toolText.value = '收起';
        needOpenStatus.value = true;
        lastml.value = false;
    }
};

const computeCol = () => {
    // 延迟加载，保证dom渲染成功
    setTimeout(() => {
        const oBox = getDomList('.search-box', props.searchRef)?.[props.index];
        const oCol = getDomList('.q-col', oBox);
        if (!oBox || !oCol) return;
        parentDOM.value = getDom('.q-row', oBox);
        inputList.value = oCol;
        box.value = oBox;
        if (oCol.length >= 4) {
            isOpen.value = true;
            setDisplay(oCol, expand.value ? 'block' : 'none');
        } else {
            isOpen.value = false;
        }
    });
};

const handleOpen = () => {
    if (needOpenStatus.value) {
        needOpenStatus.value = false;
        lastml.value = true;
        toolText.value = '展开';
        setDisplay();
    } else {
        needOpenStatus.value = true;
        lastml.value = false;
        toolText.value = '收起';
        setDisplay(inputList.value, 'block');
    }
};

const setDisplay = (DOMList = inputList.value, displayType = 'none') => {
    DOMList?.forEach((item, i) => {
        if (i > 1 && i < DOMList.length - 1) {
            item.style.display = displayType;
        }
    });
    computedBoxHeight(displayType);
};

const computedBoxHeight = (displayType: string) => {
    if (!box.value) return;

    // 计算box的高度
    if (displayType === 'none') {
        box.value.style.height = inputList.value?.[0].offsetHeight + 'px';
    } else {
        box.value.style.height = parentDOM.value?.offsetHeight + 'px';
        if (parentDOM.value?.offsetHeight === inputList.value?.[0].offsetHeight && !lastml.value) {
            lastml.value = true;
        } else if (
            parentDOM.value?.offsetHeight !== inputList.value?.[0].offsetHeight &&
            lastml.value
        ) {
            lastml.value = false;
        }
    }
};

/**
 * @: 检测窗口发生变化
 * @param {*} useDebounceFn
 * @param {*} useResizeObserver
 * @return {*}
 */
const DebounceBoxHeight = useDebounceFn(computedBoxHeight, 100);
useResizeObserver(box, () => {
    nextTick(() => {
        DebounceBoxHeight(needOpenStatus.value ? 'block' : 'none');
    });
});

/**
 * @: 检测子级发生变化
 * @return {*}
 */
useMutationObserver(
    box,
    () => {
        nextTick(() => {
            DebounceBoxHeight(needOpenStatus.value ? 'block' : 'none');
        });
    },
    {
        attributes: true,
        childList: true,
        subtree: true
    }
);

defineExpose({
    computeCol
});
</script>

<style lang="scss">
.search-controller-box {
    .search-controller-tool {
        margin-left: 8px;
    }

    .search-controller-icon {
        position: relative;
        top: 1px;
        left: 2px;
        font-size: 18px;
    }

    .el-form-item__content {
        min-width: 228px;
    }
}

.search-form-item {
    .el-form-item__content {
        margin-left: 10px !important;
    }
}
</style>
